package com.etl.webservicenet.server;

import android.app.Application;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.NonNull;

import com.etl.webservicenet.api.ServerApi;
import com.etl.webservicenet.bean.BaseNetBean;
import com.etl.webservicenet.callback.NiceCallBack;
import com.etl.webservicenet.util.EtlSpUtil;
import com.etl.webservicenet.util.GsonUtil;
import com.etl.webservicenet.util.HeaderSignEncryptUtils;
import com.etl.webservicenet.util.LogUtil;
import com.etl.webservicenet.util.StringUtil;

import org.ksoap2.HeaderProperty;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.kxml2.kdom.Element;
import org.kxml2.kdom.Node;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

import static com.etl.webservicenet.api.ServerApi.NAME_SPACE;

/**
 * <pre>
 *     author : umbrella
 *     time   : 2021/07/30
 *     desc   :
 * </pre>
 */
public class EtlNetUtil {
    public final static int  NET_TIME_OUT=1;     //请求超时
    public final static int  NET_DATA_SUCCESS=2;  //请求成功
    public final static int  NET_ERRO=3;           //请求错误
    private Context context;
    public static EtlNetUtil getInstance(){
        return  EtlNetUtilHolder.etlNetUtil;
    }
    public static class EtlNetUtilHolder{
        private static final EtlNetUtil etlNetUtil=new EtlNetUtil();
    }
    public void setContext(Context context)
    {
        this.context=context;
    }
    public void getSimpleData(Map<String,Object> paramMap, String MethodName, NiceCallBack niceCallBack) {
        Observable.just(paramMap).map(new Function<Map<String, Object>, String>() {
            @Override
            public String apply(@org.jetbrains.annotations.NotNull Map<String, Object> stringObjectMap) throws Exception {
                String resultStr = realCall(paramMap, MethodName, niceCallBack);
                return resultStr;
            }
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnError(new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                niceCallBack.onDataFail(throwable.getMessage());
                LogUtil.e("rxjava异常",throwable.getMessage());
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                BaseNetBean commonRxData = getCommonData(s, niceCallBack);
                if(commonRxData.getSuccess().equals("true"))
                {
                    niceCallBack.onDataSuccess(commonRxData);
                }
                else
                {
                    if(commonRxData.getRntData().equals(""))
                    {
                        niceCallBack.onDataSuccess(commonRxData);
                    }
                    else
                    {
                        niceCallBack.onDataSuccess(commonRxData);
                    }
                }
            }
        });
    }
    public void getPerfectData(Map<String,Object> paramMap, String MethodName, String realMethodName,NiceCallBack niceCallBack) {
        Observable.just(paramMap).map(new Function<Map<String, Object>, String>() {
            @Override
            public String apply(@org.jetbrains.annotations.NotNull Map<String, Object> stringObjectMap) throws Exception {
                String resultStr = perfectCall(paramMap, MethodName, realMethodName, niceCallBack);
                return resultStr;
            }
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnError(new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        niceCallBack.onDataFail(throwable.getMessage());
                        LogUtil.e("rxjava异常",throwable.getMessage());
                    }
                }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                BaseNetBean commonRxData = getCommonData(s, niceCallBack);
                if(commonRxData.getSuccess().equals("true"))
                {
                    niceCallBack.onDataSuccess(commonRxData);
                }
                else
                {
                    if(commonRxData.getRntData().equals(""))
                    {
                        niceCallBack.onDataSuccess(commonRxData);
                    }
                    else
                    {
                        niceCallBack.onDataSuccess(commonRxData);
                    }
                }
            }
        });
    }
    public void upLoadImg(String MethodName,String personId,String key,String fileBase64,NiceCallBack niceCallBack)
    {
        HashMap<String, Object> params = new HashMap<String, Object>();
        String strContent = String.format("%s,%s,%s", personId, key, fileBase64);
        params.put("content", strContent);
        getPerfectData(params,MethodName,MethodName+"Result",niceCallBack);
    }
    public SoapObject commonSoapApi(Map<String,Object> paramMap, String MethodName) {
        // 指定WebService的命名空间和调用的方法名
        SoapObject rpc = new SoapObject(NAME_SPACE, MethodName);
        // 如果没有参数可以省略，第一个是，调用方法的参数名。
        Iterator<Map.Entry<String, Object>> iter = paramMap.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            rpc.addProperty(entry.getKey().toString(), entry.getValue());
            LogUtil.d("isSuccessStudyAll", "键:...." + (entry.getKey().toString() + ".....值:....." + entry.getValue()));
        }
        return rpc;
    }
    public String perfectCall(Map<String,Object> paramMap, String MethodName,String methodResultName,NiceCallBack niceCallBack) {
        // SOAP Action
        String soapAction = NAME_SPACE + MethodName;
        // EndPoint
        String endPoint = ServerApi.getEndPoint();
        SoapObject rpc = commonSoapApi(paramMap,MethodName);
        // 设置需调用WebService接口需要传入的两个参数mobileCode、userId
        // 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);

        // -=======================添加token验证。。。。。。。。
        Element[] header = new Element[1];
        header[0] = new Element().createElement(NAME_SPACE,
                "SecurityToken");
        /*Element userName = new Element().createElement(
                ServiceConstants.NAME_SPACE, "Key");
		userName.addChild(Node.TEXT, ServiceInterface.getTokenKey());
		header[0].addChild(Node.ELEMENT, userName);*/

        String timeMillis = String.valueOf(System.currentTimeMillis() / 1000);
        Element TimeStamp = new Element().createElement(
                NAME_SPACE, "TimeStamp");
        TimeStamp.addChild(Node.TEXT, timeMillis);
        header[0].addChild(Node.ELEMENT, TimeStamp);

        String randomString6 = HeaderSignEncryptUtils.getRandomString6();
        Element RandomStr = new Element().createElement(
                NAME_SPACE, "RandomStr");
        RandomStr.addChild(Node.TEXT, randomString6);
        header[0].addChild(Node.ELEMENT, RandomStr);

        String signature = HeaderSignEncryptUtils.getSignature(timeMillis, randomString6);
        Element Signature = new Element().createElement(
                NAME_SPACE, "Signature");
        Signature.addChild(Node.TEXT, signature.toUpperCase());
        header[0].addChild(Node.ELEMENT, Signature);
        LogUtil.d("CommonServiceHeader", "timeMillis = " + timeMillis);
        LogUtil.d("CommonServiceHeader", "randomString6 = " + randomString6);
        LogUtil.d("CommonServiceHeader", "singature = " + signature);
        LogUtil.d("CommonServiceHeader", "调用方法 :" + MethodName);

        envelope.headerOut = header;
        // -========---------------------======================--token的认证。。
        envelope.bodyOut = rpc;
        // 设置是否调用的是dotNet开发的WebService
        envelope.dotNet = true;
        // 等价于envelope.bodyOut = rpc;
        envelope.setOutputSoapObject(rpc);
        // 超时时间
        int timeout = 100000;
        // 这里传入服务器的地址。，。。指定wsdl的服务器的地址。
        HttpTransportSE transport = new HttpTransportSE(endPoint, timeout);
        List<HeaderProperty> list = new ArrayList<>();
        // 添加公共Header
        list.add(new HeaderProperty("User-Agent", "Android" + android.os.Build.VERSION.RELEASE
                + "(" + android.os.Build.MODEL + ")"
                + "+"
                + "ZSAQ" + "(" + getPackgeName()+ ")"));
        try {
            // 调用WebService
            LogUtil.e("CallBegin", "开始调用:" + MethodName);
            transport.call(soapAction, envelope, list);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 获取返回的数据
        SoapObject object = (SoapObject) envelope.bodyIn;
        // 获取返回的结果
        String result = "";

        if (object != null) {
            try {
                result = object.getProperty(methodResultName).toString();
                LogUtil.e("CallResult", MethodName + "返回:" + result);
            } catch (Exception e) {
                result="请求异常："+e.getMessage();
            }
        }
        return result;
    }
    public String realCall(Map<String,Object> paramMap, String MethodName, NiceCallBack niceCallBack){
        // 命名空间
        String nameSpace = NAME_SPACE;
        // 调用的方法名称//代表所有单元的课程
        String methodName = MethodName;
        // EndPoint
        String endPoint = ServerApi.getUpdateWebService();
        // SOAP Action
        String soapAction = NAME_SPACE+methodName;
        // 指定WebService的命名空间和调用的方法名
        SoapObject rpc = new SoapObject(nameSpace, methodName);
        // 设置需调用WebService接口需要传入的两个参数mobileCode、userId
        // 如果没有参数可以省略，第一个是，调用方法的参数名。
        Iterator<Map.Entry<String, Object>> iter = paramMap.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            rpc.addProperty(entry.getKey().toString(), entry.getValue());
            LogUtil.d("请求参数", "键:...." + (entry.getKey().toString() + ".....值:....." + entry.getValue()));
        }
        // 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                SoapEnvelope.VER11);
        envelope.bodyOut = rpc;
        // 设置是否调用的是dotNet开发的WebService
        envelope.dotNet = true;
        // 等价于envelope.bodyOut = rpc;
        envelope.setOutputSoapObject(rpc);
        // 这里传入服务器的地址。，。。指定wsdl的服务器的地址。
        HttpTransportSE transport = new HttpTransportSE(endPoint);
        String result = "";
        try {
            // 调用WebService
            transport.call(soapAction, envelope);
        } catch (Exception e) {
            result="请求异常"+e.getMessage();
        }
        // 获取返回的数据
        SoapObject object = (SoapObject) envelope.bodyIn;
        // 获取返回的结果
        try {
            result = object.getProperty(MethodName+"Result").toString();
        } catch (NullPointerException e) {
            result="请求异常"+e.getMessage();
        }
        return result;
    }
    /**
     * 返回commonData
     * @return
     */
    public static BaseNetBean getCommonData(String json, NiceCallBack niceCallBack) {
        BaseNetBean commonData = new BaseNetBean();
        if (StringUtil.isEmpty(json)) {
            initBaseNetBean(commonData,1);
        } else {
            if(json.equals("请求异常"))
            {
                initBaseNetBean(commonData,0);
            }
            else
            {
                try {
                    BaseNetBean baseNetBean = GsonUtil.getGsonInstance().fromJson(json, BaseNetBean.class);
                    if(baseNetBean.getSuccess().equals("false"))
                    {
                        commonData=initBaseData(commonData,baseNetBean.getMsg(),baseNetBean.getSuccess(),baseNetBean.getRntData());
                    }
                    else
                    {
                        commonData=initBaseData(commonData,baseNetBean.getMsg(),baseNetBean.getSuccess(),baseNetBean.getRntData());
                    }
                } catch (Exception e) {
                    commonData.setRntData(json);
                    initBaseNetBean(commonData,0);
                }
            }
        }
        return commonData;
    }

    /**
     * @param type 0 网络无法访问  1 请求超时
     * @return
     */
    public static BaseNetBean initBaseNetBean(BaseNetBean baseNetBean, int type) {
        baseNetBean.setSuccess("false");
        switch (type)
        {
            case 0:
                baseNetBean.setMsg("网络无法访问,请检查网络连接");
                break;
            case 1:
                baseNetBean.setMsg("请求超时");
                break;
        }
        return baseNetBean;
    }
    public static String getPackgeName()
    {
        String packgeName = (String) EtlSpUtil.getInstance().getData("packgeName", "com.etl.firecontrol");
        return packgeName;
    }
    public static BaseNetBean initBaseData(BaseNetBean netBean,String msg,String Success,String RntData)
    {
        netBean.setSuccess(Success);
        netBean.setMsg(msg);
        netBean.setRntData(RntData);
        return netBean;
    }
}
